package example.demo.component.collect;

import org.springframework.aop.config.AopConfigUtils;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.data.util.ProxyUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

//@Component
//@Deprecated
public class CollectTagByBeanPostProcessor implements BeanPostProcessor, ResourceLoaderAware {

    /*ApplicationContext 实现了 ResourceLoader*/
    private ResourceLoader resourceLoader;

    public final static Map<String, String> path = new HashMap<>();
    CachingMetadataReaderFactory cachingMetadataReaderFactory;

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
        cachingMetadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
    }

    /**
     * <? AbstractAutoProxyCreator的这个方法直接return bean,也就是aop并没有作用这个点
     * <p>
     * [org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration$JdbcStoreTypeConfiguration$$Lambda$606/630949334.class]
     * 一个是@Cofiguration就会被cglib代理,这个注解有个属性，可以不用cglib代理
     * [example/demo/QuartzSimpleUseApp$$EnhancerBySpringCGLIB$$4378b086.class]-->$$EnhancerBySpringCGLIB$$
     * lambda的类也拿不到
     * <p>
     * 都拿不到MetadataReader，你去拿就报错
     */

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        try {
            MetadataReader metadataReader = cachingMetadataReaderFactory.getMetadataReader(bean.getClass().getName());
            AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
            String annotationName = CollectTag.class.getName();
            Set<MethodMetadata> annotatedMethods = metadata.getAnnotatedMethods(annotationName);
            if (annotatedMethods.size() == 0) {
                return bean;
            }
            Map<String, Object> classMetadataAnnotationAttributes = metadata.getAnnotationAttributes(RequestMapping.class.getName());
            String parentPath = classMetadataAnnotationAttributes.get("path") == null ?
                    ((String[]) classMetadataAnnotationAttributes.get("value"))[0] :
                    ((String[]) classMetadataAnnotationAttributes.get("path"))[0];
            annotatedMethods.stream().forEach(methodMetadata -> {
                Map<String, Object> methodAnnotationAttributes = methodMetadata.getAnnotationAttributes(RequestMapping.class.getName());
                String childPath = methodAnnotationAttributes.get("path") == null ?
                        ((String[]) classMetadataAnnotationAttributes.get("value"))[0] :
                        ((String[]) classMetadataAnnotationAttributes.get("path"))[0];
                String url = parentPath + childPath;
                System.out.println("url====" + url);
            });
        } catch (IOException e) {
//            e.printStackTrace();
        }
        return bean;
    }

    /**
     * bean可能是aop
     */
    @Deprecated
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
//        if (AopUtils.isAopProxy(bean)) {
//            /*拿到被代理对象的class对象*/
//            Class<?> targetClass = AopUtils.getTargetClass(bean);
//            /**<? 获取代理对象的被代理对象*/
//            Object singletonTarget = AopProxyUtils.getSingletonTarget(bean);
//            Class<?> aClass = singletonTarget.getClass();
//        }
        CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
        MetadataReader metadataReader = null;
        try {
            // 获取这个类的AnnotationMetadata
            metadataReader = cachingMetadataReaderFactory.getMetadataReader(bean.getClass().getName());
            AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();

            // 获取有CollecTag的方法集合
            Set<MethodMetadata> annotatedMethods = annotationMetadata.getAnnotatedMethods(CollectTag.class.getName());

            // 遍历结合
            for (MethodMetadata annotatedMethod : annotatedMethods) {
                MergedAnnotations annotations = metadataReader.getAnnotationMetadata().getAnnotations();
                MergedAnnotation<RequestMapping> annotation = annotations.get(RequestMapping.class);
                AnnotationAttributes annotationAttributes1 = annotation.asAnnotationAttributes(MergedAnnotation.Adapt.ANNOTATION_TO_MAP);
                String[] value1 = annotationAttributes1.getStringArray("path");
                for (String s1 : value1) {
                    path.put(s1, bean.getClass().getName());
                }

            }

        } catch (IOException e) {

        }
        return bean;
    }

}
